﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using TimeTableManagement.Entities;
using TimeTableManagement;
using System.Web.Script.Serialization;
using System.Collections;

namespace TimeTableManagement.Controllers
{
    [Authorize]
    public class TimeTableController : Controller
    {
        private QLSVContext db = new QLSVContext();
        //
        // GET: /TimeTable/

        public ViewResult Index()
        {
            var hkactive = db.Tb_Config.Where(g => g.keyword.Equals("termactive"));
            int HK = 0;
            foreach (Tb_Config _c in hkactive)
            {
                HK = Int32.Parse(_c.value);
                if (HK != 0) break;
            }
            ViewBag.HK = HK;
            if (HK == 0)
            {
                
                ModelState.AddModelError("", "Error System Timetable");
                return View();
            }
            
            var tb_timetable = db.Tb_Timetable.Include(t => t.Tb_Config).Include(t => t.Tb_Course).Include(t => t.Tb_People).Include(t => t.Tb_Room).Include(t => t.Tb_Slot).Where(g=>g.id_term==HK);
            return View(tb_timetable.ToList());
        }

        //
        // GET: /TimeTable/Details/5

        public ViewResult Details(int id)
        {
            Tb_Timetable tb_timetable = db.Tb_Timetable.Find(id);
            return View(tb_timetable);
        }

        //
        // GET: /TimeTable/Create

        public ActionResult Create()
        {
            ViewBag.id_term = new SelectList(db.Tb_Config.Where(g => g.option.Equals("term")), "id", "displayword");
            ViewBag.id_course = new SelectList(db.Tb_Course, "id", "name");
            ViewBag.id_lecturer = new SelectList(db.Tb_People.Where(g => g.type==14), "id", "name");
            ViewBag.id_room = new SelectList(db.Tb_Room, "id", "name");
            ViewBag.id_slot = new SelectList(db.Tb_Slot, "id", "slot");
            return View();
        } 

        //
        // POST: /TimeTable/Create

        [HttpPost]
        public ActionResult Create(Tb_Timetable tb_timetable, String timetablejson)
        {
            if (ModelState.IsValid)
            {
                List<TimeTable> list = new List<TimeTable>();
                JavaScriptSerializer jss = new JavaScriptSerializer();
                list = jss.Deserialize<List<TimeTable>>(timetablejson);
                foreach (TimeTable t in list)
                {
                    Tb_Timetable timetable = new Tb_Timetable();
                    timetable.id_course = t.id_course;
                    timetable.id_lecturer = t.id_lecturer;
                    timetable.id_room = t.id_room;
                    timetable.id_slot = t.id_slot;
                    timetable.id_term = tb_timetable.id_term;
                    timetable.status = tb_timetable.status;
                    timetable.count = tb_timetable.count;
                    db.Tb_Timetable.Add(timetable);
                }
                db.SaveChanges();
                return RedirectToAction("Index");  
            }

            ViewBag.id_term = new SelectList(db.Tb_Config.Where(g => g.option.Equals("term")), "id", "displayword");
            ViewBag.id_course = new SelectList(db.Tb_Course, "id", "name");
            ViewBag.id_lecturer = new SelectList(db.Tb_People.Where(g => g.type == 14), "id", "name");
            ViewBag.id_room = new SelectList(db.Tb_Room, "id", "name");
            ViewBag.id_slot = new SelectList(db.Tb_Slot, "id", "slot");
            return View();
        }

        [HttpPost]
        public ActionResult ProcessCreateAuto(int term, String timetablejson)
        {
            if (ModelState.IsValid)
            {
                List<TimeTable> list = new List<TimeTable>();
                JavaScriptSerializer jss = new JavaScriptSerializer();
                list = jss.Deserialize<List<TimeTable>>(timetablejson);
                foreach (TimeTable t in list)
                {
                    Tb_Timetable timetable = new Tb_Timetable();
                    timetable.id_course = t.id_course;
                    timetable.id_lecturer = t.id_lecturer;
                    timetable.id_room = t.id_room;
                    timetable.id_slot = t.id_slot;
                    timetable.id_term = term;
                    timetable.status = true;
                    timetable.count = 0;
                    db.Tb_Timetable.Add(timetable);
                }
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            ViewBag.id_term = new SelectList(db.Tb_Config.Where(g => g.option.Equals("term")), "id", "displayword");
            ViewBag.id_course = new SelectList(db.Tb_Course, "id", "name");
            ViewBag.id_lecturer = new SelectList(db.Tb_People.Where(g => g.type == 14), "id", "name");
            ViewBag.id_room = new SelectList(db.Tb_Room, "id", "name");
            ViewBag.id_slot = new SelectList(db.Tb_Slot, "id", "slot");
            return RedirectToAction("Index","TimeTable");
        }
        
        //
        // GET: /TimeTable/Edit/5
 
        public ActionResult Edit(int id)
        {
            Tb_Timetable tb_timetable = db.Tb_Timetable.Find(id);
            ViewBag.id_term = new SelectList(db.Tb_Config.Where(g => g.option.Equals("term")), "id", "displayword", tb_timetable.id_term);
            ViewBag.id_course = new SelectList(db.Tb_Course, "id", "name", tb_timetable.id_course);
            ViewBag.id_lecturer = new SelectList(db.Tb_People.Where(g => g.type==14), "id", "name", tb_timetable.id_lecturer);
            ViewBag.id_room = new SelectList(db.Tb_Room, "id", "name", tb_timetable.id_room);
            ViewBag.id_slot = new SelectList(db.Tb_Slot, "id", "slot", tb_timetable.id_slot);
            return View(tb_timetable);
        }

        //
        // POST: /TimeTable/Edit/5

        [HttpPost]
        public ActionResult Edit(Tb_Timetable tb_timetable)
        {
            if (ModelState.IsValid)
            {
                db.Entry(tb_timetable).State = EntityState.Modified;
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            ViewBag.id_term = new SelectList(db.Tb_Config, "id", "keyword", tb_timetable.id_term);
            ViewBag.id_course = new SelectList(db.Tb_Course, "id", "code", tb_timetable.id_course);
            ViewBag.id_lecturer = new SelectList(db.Tb_People, "id", "mssv", tb_timetable.id_lecturer);
            ViewBag.id_room = new SelectList(db.Tb_Room, "id", "name", tb_timetable.id_room);
            ViewBag.id_slot = new SelectList(db.Tb_Slot, "id", "slot", tb_timetable.id_slot);
            return View(tb_timetable);
        }

        //
        // GET: /TimeTable/Delete/5
 
        public ActionResult Delete(int id)
        {
            Tb_Timetable tb_timetable = db.Tb_Timetable.Find(id);
            return View(tb_timetable);
        }

        //
        // POST: /TimeTable/Delete/5

        [HttpPost, ActionName("Delete")]
        public ActionResult DeleteConfirmed(int id)
        {            
            Tb_Timetable tb_timetable = db.Tb_Timetable.Find(id);
            db.Tb_Timetable.Remove(tb_timetable);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        [HttpPost]
        public ActionResult getCourseinTerm(int idterm, String timetablejson)
        {
            List<Tb_Course> listretern = new List<Tb_Course>();
            listretern = this._getCourseinTerm(idterm, timetablejson);
            return View(listretern);
        }
        //
        //TERM => COURSE
        private List<Tb_Course> _getCourseinTerm(int idterm, String timetablejson)
        {
            List<Tb_Course> listretern = new List<Tb_Course>();
            //Lay index cua HK can tao TKB (idterm)
            int index_termnow = Int32.Parse(db.Tb_Config.Find(idterm).value);
            //Lay ra danh sach chuong trinh hoc trong Tb_Education
            var listEdu = db.Tb_Education.ToList();
            foreach (Tb_Education edu in listEdu)
            {
                //Lay hoc ky bat dau cua chuong trinh hoc
                var _termstart = db.Tb_Config.Where(g => g.keyword.Equals(edu.code));
                int termstart = Int32.Parse(_termstart.First<Tb_Config>().value); //id_term
                //Lay index cua termstart
                int index_termstart = Int32.Parse(db.Tb_Config.Find(termstart).value);
                //Hoc ky hien tai cua chuong trinh hoc
                int termofEDU = index_termnow - index_termstart + 1;
                //Lay danh sach cac mon hoc cua chuong trinh hoc
                JavaScriptSerializer jss = new JavaScriptSerializer();
                List<EduList> listeducation = jss.Deserialize<List<EduList>>(edu.listcourse);
                foreach (EduList cour in listeducation)
                {
                    if (cour.term == termofEDU)
                    {
                        //day la mon hoc can lay ra
                        Tb_Course c = db.Tb_Course.Find(cour.idcourse);
                        listretern.Add(c);
                    }
                }
            }
            if (timetablejson != "")
            {
                List<TimeTable> list2 = new List<TimeTable>();
                JavaScriptSerializer jss = new JavaScriptSerializer();
                list2 = jss.Deserialize<List<TimeTable>>(timetablejson);
                foreach (TimeTable time in list2)
                {
                    Tb_Course courseremove = db.Tb_Course.Find(time.id_course);
                    listretern.Remove(courseremove);
                }
            }
            return listretern;
        }

        [HttpPost]
        public ActionResult getLecturerinCourse(int idcourse)
        {
            List<Tb_People> listreturn = new List<Tb_People>();
            listreturn = this._getLecturerinCourse(idcourse);
            ViewBag.listlecturer = new SelectList(listreturn, "id", "name");
            return View(listreturn);
        }
        //
        //COURSE => LECTURER
        private List<Tb_People> _getLecturerinCourse(int idcourse)
        {
            List<Tb_People> listreturn = new List<Tb_People>();
            var listlecturer = db.Tb_People.Where(g => g.type == 14).ToList();
            foreach (Tb_People lecturer in listlecturer)
            {
                try
                {
                    //LIst mon hoc gv da dang ky
                    Tb_Profile_Value profile = db.Tb_Profile_Value
                        .Where(g => g.id_person == lecturer.id)
                        .Where(h => h.id_keyworkprofile == 25).First<Tb_Profile_Value>();
                    if (profile != null)
                    {
                        String js = profile.value;
                        JavaScriptSerializer jss = new JavaScriptSerializer();
                        List<AssignCourse> listcourse = jss.Deserialize<List<AssignCourse>>(js);
                        foreach (AssignCourse assc in listcourse)
                        {
                            if (assc.id == idcourse)
                            {
                                listreturn.Add(lecturer);
                            }
                        }
                    }
                }
                catch { }
            }
            return listreturn;
        }

        [HttpPost]
        public ActionResult getRoominCourse(int idcourse)
        {
            List<Tb_Room> listreturn = new List<Tb_Room>();
            listreturn = this._getRoominCourse(idcourse);
            ViewBag.listroom = new SelectList(listreturn, "id", "name");
            return View(listreturn);
        }
        //
        //COURSE => ROOM
        private List<Tb_Room> _getRoominCourse(int idcourse)
        {
            List<Tb_Room> listreturn = new List<Tb_Room>();
            try
            {
                Tb_Course course = db.Tb_Course.Find(idcourse);
                int? coursetype = course.type;
                //coursetype => roomtype
                Tb_Config _room = db.Tb_Config.Find(coursetype);
                int roomtype = Int32.Parse(_room.value);
                listreturn = db.Tb_Room.Where(g => g.type == roomtype).ToList();
            }
            catch { }
            return listreturn;
        }

        [HttpPost]
        public ActionResult getSlotinRoom_Lecturer(int idterm, int idroom, int idlecturer)
        {
            List<Tb_Slot> listreturn = new List<Tb_Slot>();
            listreturn = this._getSlotinRoom_Lecturer(idterm, idroom, idlecturer);
            ViewBag.slot = new SelectList(listreturn, "id", "slot");
            return View(listreturn);
        }
        //
        //ROOM & LECTURER => SLOT
        private List<Tb_Slot> _getSlotinRoom_Lecturer(int idterm, int idroom, int idlecturer)
        {
            List<Tb_Slot> listreturn = new List<Tb_Slot>();
            try
            {
                //Lay danh sach slot ma giang vien dang ky
                var _listslot = db.Tb_Profile_Value.Where(g => g.id_person == idlecturer).Where(h => h.id_keyworkprofile == 41);
                String js = _listslot.First<Tb_Profile_Value>().value;
                JavaScriptSerializer jss = new JavaScriptSerializer();
                List<RegSlot> listcourse = jss.Deserialize<List<RegSlot>>(js);
                foreach (RegSlot slot in listcourse)
                {
                    var room = db.Tb_Timetable
                        .Where(g => g.id_slot == slot.id)
                        .Where(h => h.id_room == idroom)
                        .Where(t => t.id_term == idterm);
                    if (room.ToList().Count == 0)
                    {
                        Tb_Slot sss = db.Tb_Slot.Find(slot.id);
                        listreturn.Add(sss);
                    }
                }
            }
            catch { }
            return listreturn;
        }

        [HttpPost]
        public ActionResult getTimetableTem(String timetablejson)
        {
            return View(this._getTimetableTem(timetablejson));
        }
        //TIME TABLE TEMPOLOGY
        private List<TimeTable> _getTimetableTem(String timetablejson)
        {
            List<TimeTable> listreturn = new List<TimeTable>();
            JavaScriptSerializer jss = new JavaScriptSerializer();
            listreturn = jss.Deserialize<List<TimeTable>>(timetablejson);
            return listreturn;
        }
        
        [HttpPost]
        public ActionResult getSlotinLecturer(int idterm, int idlecturer)
        {
            List<Tb_Slot> listreturn = new List<Tb_Slot>();
            listreturn = this._getSlotinLecturer(idterm, idlecturer);
            ViewBag.slot = new SelectList(listreturn, "id", "slot");
            return View(listreturn);
        }
        //
        //LECTURER => SLOT
        private List<Tb_Slot> _getSlotinLecturer(int idterm, int idlecturer)
        {
            List<Tb_Slot> listreturn = new List<Tb_Slot>();
            try
            {
                //Lay danh sach slot ma giang vien dang ky
                var _listslot = db.Tb_Profile_Value.Where(g => g.id_person == idlecturer).Where(h => h.id_keyworkprofile == 41);
                String js = _listslot.First<Tb_Profile_Value>().value;
                JavaScriptSerializer jss = new JavaScriptSerializer();
                List<RegSlot> listcourse = jss.Deserialize<List<RegSlot>>(js);
                foreach (RegSlot slot in listcourse)
                {
                    var lecturerslot = db.Tb_Timetable
                        .Where(g => g.id_slot == slot.id)
                        .Where(h => h.id_lecturer == idlecturer)
                        .Where(t=>t.id_term == idterm);
                    if (lecturerslot.ToList().Count == 0) //chua co day
                    {
                        Tb_Slot sss = db.Tb_Slot.Find(slot.id);
                        listreturn.Add(sss);
                    }
                }
            }
            catch { }
            return listreturn;
        }
        
        [HttpPost]
        public ActionResult getRoomInSlot_Course(int idterm, int idslot, int idcourse)
        {
            List<Tb_Room> listreturn = new List<Tb_Room>();
            listreturn = this._getRoomInSlot_Course(idterm, idslot, idcourse);
            ViewBag.listroom = new SelectList(listreturn, "id", "name");
            return View(listreturn);
        }
        //
        //SLOT & COURSE => ROOM
        private List<Tb_Room> _getRoomInSlot_Course(int idterm, int idslot, int idcourse)
        {
            List<Tb_Room> listreturn = new List<Tb_Room>();
            try
            {
                Tb_Course course = db.Tb_Course.Find(idcourse);
                int? coursetype = course.type;
                //coursetype => roomtype
                Tb_Config _room = db.Tb_Config.Find(coursetype);
                int roomtype = Int32.Parse(_room.value);
                listreturn = db.Tb_Room.Where(g => g.type == roomtype).ToList();
                foreach(Tb_Room room in listreturn)
                {
                    var lecturerslot = db.Tb_Timetable
                            .Where(g => g.id_slot == idslot)
                            .Where(h => h.id_room == room.id)
                            .Where(t=>t.id_term == idterm);
                    if (lecturerslot.ToList().Count != 0)
                    {
                        Tb_Room roomremove = db.Tb_Room.Find(room.id);
                        listreturn.Remove(roomremove);
                    }
                }
            }
            catch { }
            return listreturn;
        }
        
        public ActionResult CreateAuto()
        {
            var hk = db.Tb_Config.Where(g => g.option.Equals("term"));
            ViewBag.term = new SelectList(hk, "id", "displayword");
            return View(new List<TimeTable>());
        }
        [HttpPost]
        public ActionResult CreateAutoResurt(int term, int thuattoan)
        {
            if (ModelState.IsValid)
            {
                ViewBag.nameterm = db.Tb_Config.Find(term);
                List<TimeTable> ListTimeTable = new List<TimeTable>();
                if(thuattoan==1)
                    ListTimeTable = this.thuattoan1(term);
                if (thuattoan == 2)
                    ListTimeTable = this.thuattoan2(term);
                if (thuattoan == 3)
                    ListTimeTable = this.thuattoan3(term);
                if (ListTimeTable != null)
                {
                    ViewBag.kq = "yes";
                    return View(ListTimeTable);
                }
            }
                ViewBag.kq = "no";
                return View(new List<TimeTable>());
        }


        private List<TimeTable> thuattoan1(int term)
        {
            List<TimeTable> ListTimeTable = new List<TimeTable>();
            IDictionary<Tb_Course, IDictionary<Tb_People, IDictionary<Tb_Slot, List<Tb_Room>>>> DATA
                = new Dictionary<Tb_Course, IDictionary<Tb_People, IDictionary<Tb_Slot, List<Tb_Room>>>>();
            DATA = this._GetData(term);
            bool breakall = false;
            if (DATA != null)
            {
                foreach (var loop1 in DATA)
                {
                    TimeTable timetable = new TimeTable();
                    //Start loop 1
                    Tb_Course course_is_selected = loop1.Key;
                    timetable.id_course = course_is_selected.id;
                    timetable.code_course = course_is_selected.code;
                    timetable.name_course = course_is_selected.name;
                    if(loop1.Value.Count!=0)
                    foreach (var loop2 in loop1.Value)
                    {
                        //Start loop 2
                        Tb_People lecturer_is_selected = loop2.Key;
                        timetable.id_lecturer = lecturer_is_selected.id;
                        timetable.name_lecturer = lecturer_is_selected.name;
                        timetable.yesorno = false;
                        if (loop2.Value.Count == 0) breakall = false;
                        else
                        foreach (var loop3 in loop2.Value)
                        {
                            //Start loop 3
                            Tb_Slot slot_is_selectec = loop3.Key;
                            timetable.id_slot = slot_is_selectec.id;
                            timetable.name_slot = slot_is_selectec.slot;
                            if (loop3.Value.Count != 0)
                            foreach (var loop4 in loop3.Value)
                            {
                                Tb_Room room_is_seletec = loop4;
                                timetable.id_room = room_is_seletec.id;
                                timetable.name_room = room_is_seletec.name;

                                bool check = this.SelectTimeTable(ListTimeTable, timetable);
                                if (check)
                                {
                                    timetable.yesorno = true;
                                    //ListTimeTable.Add(timetable);
                                    breakall = true;
                                    break;
                                }
                                else breakall = false;
                            }
                            if (breakall) break;
                            //End loop 3
                        }
                        if (breakall) break;
                        //End loop 2
                    }
                    ListTimeTable.Add(timetable);
                    
                    //End loop 1
                }
                return ListTimeTable;
            }
            return null;
        }
        
        //Thuat toan cua Thanhnt - so 1
        private List<TimeTable> thuattoan2(int term)
        {
            List<TimeTable> ListTimeTable = new List<TimeTable>();
            IDictionary<Tb_Course, IDictionary<Tb_People, IDictionary<Tb_Slot, List<Tb_Room>>>> DATA
                = new Dictionary<Tb_Course, IDictionary<Tb_People, IDictionary<Tb_Slot, List<Tb_Room>>>>();
            DATA = this._GetData(term);
            if (DATA != null)
            {
                while (DATA.Keys.Count != 0)
                {
                    //Step 1: Select Course
                    int q = new Random().Next(DATA.Keys.Count);
                    KeyValuePair<Tb_Course, IDictionary<Tb_People, IDictionary<Tb_Slot, List<Tb_Room>>>>
                        course_is_selected = DATA.ElementAt(q);

                    TimeTable timetable = new TimeTable();
                    timetable.id_course = course_is_selected.Key.id;
                    timetable.code_course = course_is_selected.Key.code;
                    timetable.name_course = course_is_selected.Key.name;

                    //Step 2: Select Lecturer
                    IDictionary<Tb_People, IDictionary<Tb_Slot, List<Tb_Room>>> ListLecturer
                        = course_is_selected.Value;
                    //back to here, step 2
                    int solan_1 = 1;
                    bool yc_back_2 = true;
                    while (yc_back_2)
                    {
                        yc_back_2 = false;
                        IDictionary<Tb_People, IDictionary<Tb_Slot, List<Tb_Room>>> lecturer_is_selected
                        = this.SelectLecturer(ListTimeTable, ListLecturer, solan_1);
                        if (lecturer_is_selected != null)
                        {
                            timetable.id_lecturer = lecturer_is_selected.First().Key.id;
                            timetable.name_lecturer = lecturer_is_selected.First().Key.name;
                            //Step 3: Select Slot
                            IDictionary<Tb_Slot, List<Tb_Room>> ListSlot
                               = lecturer_is_selected.First().Value;
                            //back to here,step 3
                            int solan_2 = 1;
                            bool yc_back_3 = true;
                            while (yc_back_3)
                            {
                                yc_back_3 = false;
                                IDictionary<Tb_Slot, List<Tb_Room>> slot_is_selected
                                    = this.SelectSlot(lecturer_is_selected.First(), ListTimeTable, solan_2);
                                if (slot_is_selected != null)
                                {

                                    timetable.id_slot = slot_is_selected.First().Key.id;
                                    timetable.name_slot = slot_is_selected.First().Key.slot;
                                    //Step 4: Select Room
                                    List<Tb_Room> ListRoom = slot_is_selected.First().Value;
                                    int solan_3 = 1;
                                    bool yc_back_4 = true;
                                    while (yc_back_4)
                                    {
                                        yc_back_4 = false;
                                        Tb_Room room_is_selected = this.SelectRoom(ListRoom, solan_3);
                                        if (room_is_selected != null)
                                        {
                                            timetable.id_room = room_is_selected.id;
                                            timetable.name_room = room_is_selected.name;

                                            //Step 5: Check again
                                            bool checkti = this.SelectTimeTable(ListTimeTable, timetable);
                                            if (checkti)
                                            {
                                                //Xep lich thanh cong
                                                timetable.yesorno = true;
                                            }
                                            else
                                            {
                                                //Go back step 4
                                                solan_3++;
                                                yc_back_4 = true;
                                            }
                                        }
                                        else
                                        {
                                            //Go back step 3
                                            solan_2++;
                                            yc_back_3 = true;
                                        }
                                    }
                                }
                                else
                                {
                                    //Go Back Step 2
                                    solan_1++;
                                    yc_back_2 = true;
                                }
                            }
                        }
                        else
                        {
                            //Khong chon duoc giang vien
                            timetable.yesorno = false;
                        }
                    }
                    ListTimeTable.Add(timetable);
                    DATA.Remove(course_is_selected);
                }
                return ListTimeTable;
            }
            return null;
        }
        /// <summary>
        /// Tra ve gia tri chuoi string[sum slot avaliable,first slot_id,first room_id,name_slot,name_room]
        /// </summary>
        /// <param name="teacher_id"></param>
        /// <returns></returns>
        private String[] countSlotAvaliable(int term, int teacher_id, int course_id,ref List<TimeTable> current_timetable)
        {
            String[] a = new String[5];
            List<Tb_Slot> slot_avaliable = new List<Tb_Slot>();
            Tb_Slot first_slot = new Tb_Slot() ;
            Tb_Room first_room = new Tb_Room();
            // Lay danh sach cac slot ma giang vien da dang ky nhung chua day trong term do
            List<Tb_Slot> getTotalSlot = this._getSlotinLecturer(term, teacher_id);
            foreach (Tb_Slot slot in getTotalSlot)
            {
                // Kiem tra slot nay cua giang vien da ton tai trong timetable hien tai chua
                var exist_slot = current_timetable.Where(h => h.id_lecturer == teacher_id)
                                                    .Where(h => h.id_slot == slot.id);
                if (exist_slot.Count() > 0)
                {   // slot nay da dang ky trong timetable tam
                    continue;
                }
                // Lay cac phong con trong chua dang ky day cua moi slot
                List<Tb_Room> alllistroom = this._getRoomInSlot_Course(term, slot.id, course_id);
                List<Tb_Room> room_avaliable = new List<Tb_Room>();
                foreach(Tb_Room listroom in alllistroom){
                    var exist_room = current_timetable.Where(h => h.id_room == listroom.id)
                                                        .Where(h => h.id_slot == slot.id);
                    if (exist_room.Count() > 0)
                    {   // phong da duoc dang ky trong thoi khoa bieu tam
                        continue;
                    }
                    room_avaliable.Add(listroom);
                }
                if (room_avaliable.Count > 0)
                {   // slot nay co the dat phong
                    slot_avaliable.Add(slot);
                    if (first_slot.id == 0)
                    {
                        first_slot = slot;
                        first_room = room_avaliable.First();
                    }
                }
            }
            // Kiem tra tong cong co bao nhieu slot
            int sum_slot = slot_avaliable.Count;
            if (sum_slot == 0)
            {
                a[0] = a[1] = a[2] = "0";
                a[3] = a[4] = "";
            }
            else
            {
                a[0] = sum_slot.ToString();
                a[1] = first_slot.id.ToString();
                a[2] = first_room.id.ToString();
                a[3] = first_slot.slot;
                a[4] = first_room.name;
            }
            return a;
        }

        public List<TimeTable> thuattoan3(int term)
        {
            List<TimeTable> ListTimeTable = new List<TimeTable>();
            if (ModelState.IsValid)
            {
                ViewBag.nameterm = db.Tb_Config.Find(term);
                // Lay danh sach sach mon hoc va xet tren moi mon hoc
                List<Tb_Course> getlistCourse = this._getCourseinTerm(term, "");

                foreach (Tb_Course course in getlistCourse)
                {
                    // xu ly tren moi mon hoc
                    // Khai bao bien tam
                    int id_course_curent = course.id;
                    int id_lecturer_curent = 0;
                    int id_slot_current = 0;
                    int id_room_current = 0;
                    String name_course_current = course.name;
                    String name_lecturer_current = "";
                    String name_slot_current = "";
                    String name_room_current = "";
                    String code_course_current = course.code;
                    int count_best_slot_current = 0;
                    // Lay cac giang vien co the day mon hien tai
                    List<Tb_People> getlistLecturer = this._getLecturerinCourse(id_course_curent);
                    foreach (Tb_People lecturer in getlistLecturer)
                    {
                        // Xy ly tren moi giang vien
                        // Lay ra cac slot con co the cua giang vien do
                        String[] info_lecturer = countSlotAvaliable(term, lecturer.id, id_course_curent, ref ListTimeTable);
                        int avaliable_count_slot = Int32.Parse(info_lecturer[0]);
                        if (avaliable_count_slot > 0 && (count_best_slot_current > avaliable_count_slot|| count_best_slot_current == 0))
                        {
                            // truong hop giang vien hien tai uu tien hon
                            id_lecturer_curent = lecturer.id;
                            name_lecturer_current = lecturer.name;
                            id_slot_current = Int32.Parse(info_lecturer[1]);
                            name_slot_current = info_lecturer[3];
                            id_room_current = Int32.Parse(info_lecturer[2]);
                            name_room_current = info_lecturer[4];
                            count_best_slot_current = avaliable_count_slot;
                        }
                    }
                    // Ghi giang vien tot nhat vao timetable neu co
                    TimeTable newschedule = new TimeTable();
                    newschedule.id_course = id_course_curent;
                    newschedule.id_lecturer = id_lecturer_curent;
                    newschedule.id_room = id_room_current;
                    newschedule.id_slot = id_slot_current;
                    newschedule.name_course = name_course_current;
                    newschedule.name_lecturer = name_lecturer_current;
                    newschedule.name_slot = name_slot_current;
                    newschedule.name_room = name_room_current;
                    newschedule.code_course = code_course_current;
                    if (count_best_slot_current > 0)
                    {   // Co giang vien co do uu tien tot nhat
                        newschedule.yesorno = true;
                    }
                    else
                    {
                        newschedule.yesorno = false;
                    }
                    ListTimeTable.Add(newschedule);
                }

            }
            ViewBag.kq = "yes";
            return ListTimeTable;
        }

        private IDictionary<Tb_Slot, List<Tb_Room>> SelectSlot
            (KeyValuePair<Tb_People, IDictionary<Tb_Slot, List<Tb_Room>>> ListSlot, 
            List<TimeTable> ListTimeTable, int solan)
        {
            solan = solan - 1;
            if (ListSlot.Value.Count != 0 && solan < ListSlot.Value.Count)
            {
                IDictionary<Tb_Slot, List<Tb_Room>> result = new Dictionary<Tb_Slot, List<Tb_Room>>();
                //Lay slot ma giang vien chua day
                int idpeople = ListSlot.Key.id;
                //Lay ra slot co nhieu phong nhat
                int kq = ListSlot.Value.First().Value.Count;
                int index = 0;
                int i = 0;
                for (int k = 1; k <= solan; k++)
                {
                    foreach (var item in ListSlot.Value)
                    {
                        if (item.Value.Count != 0)
                        {
                            bool x = true;
                            foreach (TimeTable t in ListTimeTable)
                            {
                                if (t.id_lecturer == idpeople && t.id_slot == item.Key.id)
                                {
                                    x = false;
                                    break;
                                }
                            }
                            if (x)
                            {
                                int a = item.Value.Count;
                                if (a > kq) { kq = a; index = i; }
                            }
                        }
                        i++;
                    }
                    if (solan != 1 && k != solan)
                    {
                        ListSlot.Value.Remove(ListSlot.Value.ElementAt(index));
                        kq = ListSlot.Value.First().Value.Count;
                        index = 0;
                        i = 0;
                    }
                }
                result.Add(ListSlot.Value.ElementAt(index));
                return result;
            }
            return null;
        }

        private bool SelectTimeTable(List<TimeTable> listtimetable, TimeTable timetable)
        {
            //Step 1: Kiem tra timetable co ton tai Slot&&Room || Lecturer&&Slot trong listtimetable khong?
            foreach(TimeTable t in listtimetable)
            {
                
                if (
                    (t.id_room == timetable.id_room && t.id_slot == timetable.id_slot) 
                    ||(t.id_lecturer==timetable.id_lecturer && t.id_slot==timetable.id_slot)
                    || timetable.id_lecturer == 0
                    || timetable.id_room == 0
                    || timetable.id_slot ==0)
                { return false; }
            }
            //Step 2: Neu thoa step 1
            return true;
        }

        /// <summary>
        /// Chon Room, lay room dau tien
        /// </summary>
        /// <param name="listroom"></param>
        /// <returns></returns>
        private Tb_Room SelectRoom(List<Tb_Room> listroom, int solan)
        {
            solan = solan - 1;
            if (solan >= listroom.Count) return null;
            return listroom.ElementAt(solan);
        }

        
        /// <summary>
        /// Can cu vao danh sach giang vien, chon ra giang vien co slot/room it nhat
        /// </summary>
        /// <param name="listlecturer">Danh sach giang vien cua 1 mon hoc</param>
        /// <returns>Danh sach IDictionary chi co 1 giang vien</returns>
        private IDictionary<Tb_People, IDictionary<Tb_Slot, List<Tb_Room>>>
            SelectLecturer( List<TimeTable> ListTimeTable,
            IDictionary<Tb_People, IDictionary<Tb_Slot, List<Tb_Room>>> listlecturer, int solan)
        {
            solan = solan - 1;
            if (listlecturer.Count != 0 && solan < listlecturer.Count)
            {
                IDictionary<Tb_People, IDictionary<Tb_Slot, List<Tb_Room>>> result 
                    = new Dictionary<Tb_People, IDictionary<Tb_Slot, List<Tb_Room>>>();
                int kq = listlecturer.First().Value.Count;
                int index = 0;
                int i = 0;
                for (int k = 1; k <= solan; k++)
                {
                    foreach (var item in listlecturer)
                    {

                        int a = this.CountSlotKD(item, ListTimeTable);
                        if (a != 0 && a < kq) { kq = a; index = i; }
                        i++;
                    }
                    if (solan != 1 && k != solan)
                    {
                        listlecturer.Remove(listlecturer.ElementAt(index));
                        kq = listlecturer.First().Value.Count;
                        index = 0;
                        i = 0;
                    }
                }
                result.Add(listlecturer.ElementAt(index));
                return result;
            }
            return null;
        }

        private int CountSlotKD(KeyValuePair<Tb_People, IDictionary<Tb_Slot, List<Tb_Room>>> item, List<TimeTable> ListTimeTable)
        {
            Tb_People people = item.Key;
            IDictionary<Tb_Slot, List<Tb_Room>> listslot = item.Value;
            int count = 0;
            foreach (var slot in listslot)
            {
                foreach (TimeTable time in ListTimeTable)
                {
                    if (time.id_slot != slot.Key.id && time.id_lecturer == people.id)
                        count++;
                }
            }
            return count;
        }
        /// <summary>
        /// Lay du lieu, luu theo dang phan cap
        /// Term -> Course -> Lecturer -> Slot -> Room
        /// </summary>
        /// <param name="term"></param>
        /// <returns></returns>
        private IDictionary<Tb_Course, IDictionary<Tb_People,
            IDictionary<Tb_Slot, List<Tb_Room>>>> _GetData(int term)
        {
            try
            {
                //Mot dong trong tkb <==> Mot item trong listtimetabel
                IDictionary<Tb_Course, IDictionary<Tb_People, IDictionary<Tb_Slot, List<Tb_Room>>>> listtimetable
                    = new Dictionary<Tb_Course, IDictionary<Tb_People, IDictionary<Tb_Slot, List<Tb_Room>>>>();
                //1. rfvc Course
                List<Tb_Course> getlistCourse = this._getCourseinTerm(term, "");
                foreach (Tb_Course course in getlistCourse)
                {
                    //2. Lecturer
                    IDictionary<Tb_People, IDictionary<Tb_Slot, List<Tb_Room>>> listlecturer
                    = new Dictionary<Tb_People, IDictionary<Tb_Slot, List<Tb_Room>>>();
                    List<Tb_People> getlistLecturer = this._getLecturerinCourse(course.id);
                    foreach (Tb_People lecturer in getlistLecturer)
                    {
                        //3. Slot
                        IDictionary<Tb_Slot, List<Tb_Room>> listslot = new Dictionary<Tb_Slot, List<Tb_Room>>();
                        List<Tb_Slot> getlistSlot = this._getSlotinLecturer(term, lecturer.id);
                        foreach (Tb_Slot slot in getlistSlot)
                        {
                            //4. Room
                            List<Tb_Room> listroom = new List<Tb_Room>();
                            listroom = this._getRoomInSlot_Course(term, slot.id, course.id);
                            listslot.Add(slot, listroom);
                        }
                        listlecturer.Add(lecturer, listslot);
                    }
                    listtimetable.Add(course, listlecturer);
                }
                return listtimetable;
            }
            catch { }
            return null;
        }
        protected override void Dispose(bool disposing)
        {
            db.Dispose();
            base.Dispose(disposing);
        }
    }
}